package com.itcz.maker.meta;

import cn.hutool.core.collection.CollectionUtil;
import cn.hutool.core.date.DateUtil;
import cn.hutool.core.io.FileUtil;
import cn.hutool.core.util.StrUtil;
import com.itcz.maker.meta.enums.FileGeneratorTypeEnum;
import com.itcz.maker.meta.enums.FileTypeEnum;
import com.itcz.maker.meta.enums.ModelTypeEnum;

import java.nio.file.Paths;
import java.util.List;
import java.util.stream.Collectors;

public class MetaValidator {
    public static void doValidWithFill(Meta meta) {
        // 校验根路径
        doValidWithFillRootPath(meta);
        // 校验文件配置
        doValidWithFillFileConfig(meta);
        // 校验模型配置
        doValidWithFillModelConfig(meta);
    }

    private static void doValidWithFillModelConfig(Meta meta) {
        // modelConfig 校验和默认值
        Meta.ModelConfig modelConfig = meta.getModelConfig();
        // 降低圈复杂度
        if (modelConfig == null) {
            return;
        }
        List<Meta.ModelConfig.ModelInfo> modelInfoList = modelConfig.getModels();
        // 降低圈复杂度
        if (CollectionUtil.isEmpty(modelInfoList)) {
            return;
        }
        for (Meta.ModelConfig.ModelInfo modelInfo : modelInfoList) {
            // 如果模型的 groupKey 不为空，表示为模型组配置，则不校验 fieldName 等
            String groupKey = modelInfo.getGroupKey();
            // 如果模型类型为模型组，则不进行校验
            if(StrUtil.isNotEmpty(groupKey)) {
                List<Meta.ModelConfig.ModelInfo> models = modelInfo.getModels();
                // Java 的Stream流处理
                String allArgsStr = models.stream()
                        .map(subModelInfo -> String.format("\"--%s\"", subModelInfo.getFieldName()))
                        .collect(Collectors.joining(", "));
                modelInfo.setAllArgsStr(allArgsStr);
                continue;
            }
            // fieldName：必填
            String fieldName = modelInfo.getFieldName();
            if(StrUtil.isBlank(fieldName)) {
                throw new MetaException("未填写 fieldName");
            }

            // type：默认String
            String type = modelInfo.getType();
            if(StrUtil.isBlank(type)) {
                modelInfo.setType(ModelTypeEnum.STRING.getValue());
            }
        }
    }

    private static void doValidWithFillFileConfig(Meta meta) {
        // fileConfig 校验和默认值
        Meta.FileConfig fileConfig = meta.getFileConfig();
        // 降低圈复杂度
        if (fileConfig == null) {
            return;
        }
        // sourceRootPath:必填
        String sourceRootPath = fileConfig.getSourceRootPath();
        if(StrUtil.isBlank(sourceRootPath)) {
            throw new MetaException("未填写 sourceRootPath");
        }
        // inputRootPath: .source + sourceRootPath 最后一个层级路径
        String inputRootPath = fileConfig.getInputRootPath();
        // 通过Hutool工具包拿到sourceRootPath最后一个层级路径的文件名
        String defaultInputRootPath = ".source/" +
                FileUtil.getLastPathEle(Paths.get(sourceRootPath)).getFileName().toString();
        if(StrUtil.isEmpty(inputRootPath)) {
            fileConfig.setInputRootPath(defaultInputRootPath);
        }
        // outputRootPath:默认当前路径下的generated
        String outputRootPath = fileConfig.getOutputRootPath();
        String defaultOutputRootPath = "generated";
        if(StrUtil.isEmpty(outputRootPath)) {
            fileConfig.setOutputRootPath(defaultOutputRootPath);
        }
        // type：默认dir
        String type = fileConfig.getType();
        String defaultType = FileTypeEnum.DIR.getValue();
        if(StrUtil.isEmpty(type)) {
            fileConfig.setType(defaultType);
        }

        // fileInfo 默认值
        List<Meta.FileConfig.FileInfo> fileInfoList = fileConfig.getFiles();
        // 降低圈复杂度
        if (CollectionUtil.isEmpty(fileInfoList)) {
            return;
        }
        for (Meta.FileConfig.FileInfo fileInfo : fileInfoList) {
            String fileInfoType = fileInfo.getType();
            // 判断文件类型是否为文件组
            if(FileTypeEnum.GROUP.getValue().equals(fileInfoType)) {
                // 是则无需进行后面的校验
                continue;
            }
            // inputPath：必填
            String inputPath = fileInfo.getInputPath();
            if(StrUtil.isBlank(inputPath)) {
                throw new MetaException("未填写 inputPath");
            }

            // outputPath:默认等于 inputPath
            String outputPath = fileInfo.getOutputPath();
            if(StrUtil.isEmpty(outputPath)) {
                fileInfo.setOutputPath(inputPath);
            }

            // type：默认 inputPath 有文件后缀（如 .java）为 file，否则为 dir
            if(StrUtil.isBlank(fileInfoType)) {
                if(StrUtil.isEmpty(FileUtil.getSuffix(inputPath))){
                    fileInfo.setType(FileTypeEnum.DIR.getValue());
                } else {
                    fileInfo.setType(FileTypeEnum.FILE.getValue());
                }
            }
            // generateType：如果文件结尾不为 ftl，generateType 默认为 static，否则为 dynamic
            String generateType = fileInfo.getGenerateType();
            if(StrUtil.isBlank(generateType)) {
                // 为动态模板
                if(inputPath.endsWith(".ftl")) {
                    fileInfo.setGenerateType(FileGeneratorTypeEnum.DYNAMIC.getValue());
                } else {
                    fileInfo.setGenerateType(FileGeneratorTypeEnum.STATIC.getValue());
                }
            }
        }
    }

    private static void doValidWithFillRootPath(Meta meta) {
        // 如果name为空或者空字符串,则设置默认值
        String name = StrUtil.blankToDefault(meta.getName(), "my-generator");
        // 如歌description为空，则设置默认值
        String description = StrUtil.emptyToDefault(meta.getDescription(), "我的模板代码生成器");
        String basePackage = StrUtil.blankToDefault(meta.getBasePackage(), "com.itcz");
        String version = StrUtil.emptyToDefault(meta.getVersion(), "1.0");
        String createTime = StrUtil.emptyToDefault(meta.getCreateTime(), DateUtil.now());

        meta.setName(name);
        meta.setDescription(description);
        meta.setBasePackage(basePackage);
        meta.setVersion(version);
        meta.setCreateTime(createTime);
    }
}
